普通方法和对象方法 this 指向结论:
this的指向,是在函数被调用的时候确定的
函数调用时,看其是否被某个对象所拥有,假如被某个对象拥有,那么函数中的this,指向的是其拥有的对象
例如:obj.fn()。fn() 函数被 obj 所拥有,那么 fn 里面的 this,指向的是 obj
如果函数独立调用,那么该函数内部的this,则指向undefined。在非严格模式中,当this指向undefined时,它会被自动指向全局对象。
例如aaa() 是独立调用,那么aaa函数里面的this会指向undefined,在非严格模式下面指向的是全局对象
基础练习题
1 | var value = 1; |
独立调用,非严格模式下 this 指向全局对象
1 | // demo1 |
obj.c 里面的 this.a 是赋值语句,并没有调用,this 是在调用时被决定的,现在只是定义,默认指向全局对象,this.a === window.a
1 | // demo01 |
参考文章
进阶练习题1
1 | function Foo() { |
解析
可以看到题目中存在函数声明和变量声明,它们会被提升,变成下面
1 | function Foo() { |
开始执行语句:
Foo.getName();
找Foo函数找到getName方法 找到Foo.getName = function () { alert(2); }; 打印输出2getName();
由上面声明提升的分析得,执行getName = function () { alert (4);}; 打印输出4Foo().getName();
运算符的优先级(点.的优先级高),但是因为()括号无法.点调用,所以先将Foo函数执行完再去执行.getName()方法。
等价于(Foo()).getName(); 先看Foo函数,一个全局变量getName,一个return this,所以此时全局变量的getName再次被重新赋值。
Foo返回this,返回的就是调用Foo函数的对象,window。所以(Foo()).getName() 等价于window,getName(),getName = function () { alert(1); };,打印输出1
getName();
与上题一样,getName = function () { alert(1); };,打印输出1new Foo.getName();
因为.点的优先级高,所以等价于 new (Foo.getName)(),Foo.getName = function () { alert (2);};,new(Foo.getName)() = new ( function () { alert(2); };){},因为new函数调用时,会执行这个函数,所以打印输出2new Foo().getName();
实际为 (new Foo()).getName(),先执行 new Foo(), 结果产生一个新的实例对象,并且继承了Foo()这个构造函数中的getName方法,找到 Foo.prototype.getName = function () { alert(3); }; 打印输出3new new Foo().getName();
new ((new Foo()).getName)() => new (foo.getName)() => new (function () { alert(3); };)() 打印输出3
参考文章
进阶练习题2
1 | var name = 'window' |
答案
1 | person1.show1() // person1,隐式绑定,this指向调用者 person1 |
通过构造函数来创建一个对象,并执行相同的4个show方法
1 | /** |
答案:
1 | personA.show1() // personA,隐式绑定,调用者是 personA |
题目一和题目二的区别是,personA 通过构造函数创建,new 绑定,产生了新的构造函数作用域,在 personA.show2() 中的箭头函数,this指向外层作用域,即personA函数作用域。
参考文章
【进阶3-2期】JavaScript深入之重新认识箭头函数的this
面试题 1
1 | var a = 100 |